package com.taxshare.purchaser.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.taxshare.mybatis.pager.PageInfoRequest;
import com.taxshare.mybatis.pager.PageRequest;
import com.taxshare.purchaser.config.AsyncTreadPoolConfig;
import com.taxshare.purchaser.constant.CodeConstant;
import com.taxshare.purchaser.constant.ResultConstant;
import com.taxshare.purchaser.entity.ElectronicledgerEntity;
import com.taxshare.purchaser.entity.PeriodEntity;
import com.taxshare.purchaser.entity.excel.ElectronicledgerExcelEntity;
import com.taxshare.purchaser.mapper.ElectronicledgerMapper;
import com.taxshare.purchaser.mapper.PeriodMapper;
import com.taxshare.purchaser.remote.ApiClientService;
import com.taxshare.purchaser.remote.ManagerClientService;
import com.taxshare.purchaser.util.TransformationUtil;
import com.taxshare.purchaser.view.dto.*;
import com.taxshare.purchaser.view.vo.InvoiceResultSummaryVO;
import com.taxshare.purchaser.view.vo.InvoiceSummaryCountVO;
import com.taxshare.purchaser.view.vo.InvoiceSummaryVO;
import com.taxshare.response.beans.Response;
import com.taxshare.tools.constant.CommonConstant;
import com.taxshare.tools.util.ExcelUtil;
import com.taxshare.tools.util.UUIDUitl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hpsf.Decimal;
import org.aspectj.apache.bcel.classfile.Code;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @ClassName: ElectronicLedgerService
 * @Description: 发票电子底账以及发票认证处理
 * @author: luozhongyi
 * @date: 2021/3/25 14:54
 */
@Slf4j
@Service
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
public class ElectronicLedgerService extends ServiceImpl<ElectronicledgerMapper, ElectronicledgerEntity> {

    @Autowired
    ApiClientService apiClientService;

    @Autowired
    PeriodMapper periodMapper;

    @Autowired
    AsyncAuthService asyncAuthService;

    @Autowired
    CommService commService;

    @Autowired
    ManagerClientService managerClientService;

    @Autowired
    private AsyncTreadPoolConfig asyncTreadPoolConfig;

    /**
     * 查询
     *
     * @param dto
     * @return
     */
    public QueryWrapper<ElectronicledgerEntity> getWrapper(ElectronicLedgerDTO dto) {
        QueryWrapper<ElectronicledgerEntity> queryWrapper = new QueryWrapper();
        if (StrUtil.isNotBlank(dto.getTaxNo())) {
            queryWrapper.eq("purchaser_taxno", dto.getTaxNo());
        } else {
            List<String> taxNos = commService.getTaxNumbers();
            queryWrapper.in("purchaser_taxno", taxNos);
        }
        if (StrUtil.isNotBlank(dto.getAuthPeriod())) {
            queryWrapper.eq("auth_period", dto.getAuthPeriod().replace("-", ""));
        }
        if (StrUtil.isNotBlank(dto.getInvoiceCode())) {
            queryWrapper.eq("invoice_code", dto.getInvoiceCode());
        }
        if (StrUtil.isNotBlank(dto.getInvoiceNo())) {
            queryWrapper.eq("invoice_no", dto.getInvoiceNo());
        }
        if (StrUtil.isNotBlank(dto.getAuthState())) {
            queryWrapper.eq("auth_state", dto.getAuthState());
        }
        if (!StrUtil.hasBlank(dto.getInvoiceState())) {
            queryWrapper.eq("invoice_state", dto.getInvoiceState());
        }
        if (!StrUtil.hasBlank(dto.getSubmitMode())) {
            queryWrapper.eq("submit_mode", dto.getSubmitMode());
        }
        String menuFlag = dto.getMenuFlag();
        if (!StrUtil.hasBlank(menuFlag)) {
            if (CodeConstant.COMM_CODE_0.equals(menuFlag)) {
                if (!StrUtil.hasBlank(dto.getSubmitState())) {
                    queryWrapper.eq("submit_state", dto.getSubmitState());
                    queryWrapper.eq("submit_mode", CodeConstant.COMM_CODE_0);
                } else {
                    queryWrapper.in("submit_state", Arrays.asList(CodeConstant.COMM_CODE_0, CodeConstant.COMM_CODE_2));
                    queryWrapper.eq("submit_mode", CodeConstant.COMM_CODE_0);
                }
            } else if (CodeConstant.COMM_CODE_1.equals(menuFlag)) {
                if (!StrUtil.hasBlank(dto.getSubmitState())) {
                    queryWrapper.eq("submit_state", dto.getSubmitState());
                    queryWrapper.eq("submit_mode", CodeConstant.COMM_CODE_0);
                } else {
                    queryWrapper.in("submit_state", Arrays.asList(CodeConstant.COMM_CODE_0, CodeConstant.COMM_CODE_2));
                    queryWrapper.eq("submit_mode", CodeConstant.COMM_CODE_1);
                }
            } else {
                queryWrapper.eq("submit_state", CodeConstant.COMM_CODE_1);
            }
        } else {
            if (!StrUtil.hasBlank(dto.getSubmitState())) {
                queryWrapper.eq("submit_state", dto.getSubmitState());
            }
        }
        //勾选认证和导入勾选排除已认证的发票
        if (!StrUtil.hasBlank(dto.getAuthStateFlag())) {
            if (CodeConstant.COMM_CODE_00.equals(dto.getAuthStateFlag())) {
                queryWrapper.eq("auth_state", CodeConstant.COMM_CODE_1);
                queryWrapper.eq("submit_state", CodeConstant.COMM_CODE_1);
            } else if (CodeConstant.COMM_CODE_1.equals(dto.getAuthStateFlag())) {
                queryWrapper.ne("auth_state", dto.getAuthStateFlag());
            }
        }
        if (StrUtil.isNotBlank(dto.getInvoiceDateStart()) && StrUtil.isNotBlank(dto.getInvoiceDateEnd())) {
            queryWrapper.apply("date_format(invoice_date,'%Y-%m-%d') >= {0}", dto.getInvoiceDateStart())
                    .apply("date_format(invoice_date,'%Y-%m-%d') <= {0}", dto.getInvoiceDateEnd());
        } else if (StrUtil.isNotBlank(dto.getInvoiceDateStart())) {
            queryWrapper.apply("date_format(invoice_date,'%Y-%m-%d') >= {0}", dto.getInvoiceDateStart());
        } else if (StrUtil.isNotBlank(dto.getInvoiceDateEnd())) {
            queryWrapper.apply("date_format(invoice_date,'%Y-%m-%d') <= {0}", dto.getInvoiceDateEnd());
        }
        queryWrapper.orderByDesc("invoice_date");
        return queryWrapper;
    }

    public Response<IPage<ElectronicledgerEntity>> list(PageRequest<ElectronicLedgerDTO> query) {
         /*IPage<List<Map<String,Object>>> result =
                baseMapper.selectPageByParam(new Page<>(pageInfoRequest.getCurrentPage(),pageInfoRequest.getPageSize()),queryWrapper);*/
        PageInfoRequest pageInfoRequest = query.getPage();
        IPage<ElectronicledgerEntity> result =
                baseMapper.selectPage(new Page<>(pageInfoRequest.getCurrentPage(), pageInfoRequest.getPageSize()), this.getWrapper(query.getInfo()));
        return Response.success(result);
    }

    public void exportResultExcel(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception {
        ElectronicLedgerDTO electronicLedgerDTO=queryWrapper(request);

        List<ElectronicledgerEntity> electronicledgerEntities = baseMapper.selectList(this.getWrapper(electronicLedgerDTO));

        List<ElectronicledgerExcelEntity> excelEntities = new ArrayList<>();
        electronicledgerEntities.forEach(data -> {
            ElectronicledgerExcelEntity excelEntity = new ElectronicledgerExcelEntity();
            BeanUtils.copyProperties(data, excelEntity);
            excelEntity.setManagementState("0".equals(data.getManagementState()) ? "正常" : "非正常");
            excelEntity.setAuthState(TransformationUtil.transAuthState(data.getAuthState()));
            excelEntity.setInvoiceType(TransformationUtil.transInvoiceTypeName(data.getInvoiceType()));
            excelEntity.setAuthResult(TransformationUtil.transAuthResult(data.getAuthResult()));
            excelEntities.add(excelEntity);
        });

        List<String> cols = ExcelDTO.electronicCols;
        Map<String, String> map = MapUtil.of("authTime", "认证操作时间");
        map.put("authUsername", "认证人员");
        map.put("invoiceType", "发票类型");
        map.put("invoiceCode", "发票代码");
        map.put("invoiceNo", "发票号码");
        map.put("invoiceDate", "开票日期");
        map.put("purchaserName", "购方名称");
        map.put("purchaserTaxno", "购方税号");
        map.put("sellerName", "销方名称");
        map.put("sellerTaxno", "销方税号");
        map.put("amoutWithTax", "金额(不含税)");
        map.put("taxAmout", "税额");
        map.put("validTax", "有效税额");
        map.put("totalAmout", "价税合计");
        map.put("authPeriod", "税款所属期");
        map.put("authState", "认证状态");
        map.put("authResult", "认证结果");
        map.put("authResultContent", "认证结果内容");
        map.put("managementState", "管理状态");

        ExcelUtil.exportExcel(httpServletResponse, cols, map, excelEntities, "认证结果");

    }

    //拼装查询条件
    private ElectronicLedgerDTO queryWrapper(HttpServletRequest request) {
        ElectronicLedgerDTO entity = new ElectronicLedgerDTO();
        if (StrUtil.isNotBlank(request.getParameter("authPeriod"))) {
            entity.setAuthPeriod(request.getParameter("authPeriod"));
        }
        if (StrUtil.isNotBlank(request.getParameter("authState"))) {
            entity.setAuthState(request.getParameter("authState"));
        }
        if (StrUtil.isNotBlank(request.getParameter("invoiceCode"))) {
            entity.setInvoiceCode(request.getParameter("invoiceCode"));
        }
        if (StrUtil.isNotBlank(request.getParameter("invoiceNo"))) {
            entity.setInvoiceNo(request.getParameter("invoiceNo"));
        }
        if (StrUtil.isNotBlank(request.getParameter("invoiceDateEnd"))) {
            entity.setInvoiceDateEnd(request.getParameter("invoiceDateEnd"));
        }
        if (StrUtil.isNotBlank(request.getParameter("invoiceDateStart"))) {
            entity.setInvoiceDateStart(request.getParameter("invoiceDateStart"));
        }
        if (StrUtil.isNotBlank(request.getParameter("invoiceNo"))) {
            entity.setInvoiceNo(request.getParameter("invoiceNo"));
        }
        if (StrUtil.isNotBlank(request.getParameter("taxNo"))) {
            entity.setTaxNo(request.getParameter("taxNo"));
        }
        return entity;
    }

    /**
     * 电子底账初始化全量数据
     *
     * @param bean
     * @return
     */
    public Response electronicLedgerInit(InvoiceSyncDTO bean) {
        //调接口全量初始化电子底账发票
        callRemoteService(bean.getNsrsbh(), CodeConstant.FULL_SYNCHRONIZATION, null);
        //更新初始化标记 以便后面每天增量更新
        updateCompanyInitFlag(bean.getNsrsbh());
        //调接口增量初始化电子底账发票
        return callRemoteService(bean.getNsrsbh(), CodeConstant.DEFAULT_SYNCTYPE, null);
    }

    /**
     * 页面触发按开票日期同步
     *
     * @param bean
     * @return
     */
    public Response electronicLedgerSyn(InvoiceSyncDTO bean) {
        if (StrUtil.hasBlank(bean.getNsrsbh())) {
            return Response.error(ResultConstant.RET_P0001_CODE, ResultConstant.RET_P0001_MSG);
        } else if (StrUtil.hasBlank(bean.getSynccondition())) {
            return Response.error(ResultConstant.RET_P0002_CODE, ResultConstant.RET_P0002_MSG);
        }
        //按照选择日期进行同步发票
        return callRemoteService(bean.getNsrsbh(), CodeConstant.DATE_SYNCHRONIZATION, bean.getSynccondition());
    }

    /**
     * 刷新税款所属期
     *
     * @param taxNo
     * @return
     */
    public Response refreshPeriod(String taxNo) {
        Response response = apiClientService.period(taxNo);
        if (CodeConstant.T0000.equals(response.getCode())) {
            asyncAuthService.updatePeriodByTaxNo(taxNo, response);
        } else {
            return Response.error(CodeConstant.ERROR, response.getMsg());
        }
        return Response.success();
    }

    /**
     * 获取公司税款所属期
     *
     * @param taxNo
     * @return
     */
    public Response getTaxNoPeriod(String taxNo) {
        QueryWrapper<PeriodEntity> queryWrapper = new QueryWrapper();
        queryWrapper.eq("tax_number", taxNo);
        PeriodEntity periodEntity = periodMapper.selectOne(queryWrapper);
        return Response.success(periodEntity);
    }

    /**
     * 发票同步
     *
     * @param nsrsbh
     * @param type
     * @param synccondition
     * @throws NoSuchFieldException
     */
    public Response callRemoteService(String nsrsbh, String type, String synccondition) {
        InvoiceSyncDTO zptbBean = new InvoiceSyncDTO();
        zptbBean.setNsrsbh(nsrsbh);
        zptbBean.setSynctype(type);
        zptbBean.setSynccondition(synccondition);
        Response response = apiClientService.sync(zptbBean);
        //如果是05、07不进行数据处理
        if (CodeConstant.FULL_SYNCHRONIZATION.equals(type) || CodeConstant.COMPLETION_NOTIFICATIONS.equals(type)) {
            return Response.success();
        }
        return analyticalResult(response, nsrsbh);
    }

    /**
     * 解析接口返回结果
     *
     * @param response
     * @param nsrsbh
     * @return
     */
    private Response analyticalResult(Response response, String nsrsbh) {
        if (CodeConstant.T0000.equals(response.getCode())) {
            Map<String, String> map = JSONUtil.toBean(response.getData().toString(), Map.class);
            //属期保存
            asyncAuthService.saveTaxPeriod(nsrsbh, map.get("Period"), map.get("OperationDateEnd"));
            //同步业务数据
            List<InvoiceListDTO> dzdzList = JSON.parseArray(JSON.toJSONString(map.get("InvoiceList")), InvoiceListDTO.class);
            if (dzdzList.size() > 0) {
                //数据入库处理
                dataStorageHandling(dzdzList);
            }
            //判断是不是06/07调用方式
            if (null != map.get("ContinueFlag")) {
                //发票数量大于0，调用07回调通知，为0不需要回调通知
                if (0 < MapUtils.getIntValue(map, "InvoiceQuantity", 0)) {
                    callRemoteService(nsrsbh, CodeConstant.COMPLETION_NOTIFICATIONS, map.get("TaskNo"));
                }
                if ("Y".equals(map.get("ContinueFlag"))) {
                    callRemoteService(nsrsbh, CodeConstant.DEFAULT_SYNCTYPE, null);
                }
            }
        } else {
            log.error("电子底账同步失败：{}", JSONUtil.toJsonStr(response));
            return Response.error(CodeConstant.ERROR, response.getMsg());
        }
        return Response.success();
    }

    /**
     * 数据入库处理,
     *
     * @param invoices 接口返回数据
     * @return 返回新增数据
     */
    private void dataStorageHandling(List<InvoiceListDTO> invoices) {
        for (InvoiceListDTO dto : invoices) {
            ElectronicledgerEntity entity = invoiceIsExists(dto);
            //发票存在
            if (entity != null) {
                updateData(dto, entity);
            } else {
                saveData(dto);
            }
        }
    }

    /**
     * @param dto
     * @return
     */
    private ElectronicledgerEntity invoiceIsExists(InvoiceListDTO dto) {
        QueryWrapper<ElectronicledgerEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("invoice_code", dto.getInvoiceCode());
        queryWrapper.eq("invoice_no", dto.getInvoiceNo());
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 电子底账库插入
     *
     * @param dto
     */
    private void saveData(InvoiceListDTO dto) {
        ElectronicledgerEntity entity = new ElectronicledgerEntity();
        BeanUtil.copyProperties(dto, entity);
        entity.setInvoiceId(UUIDUitl.UUID32(false));
        entity.setTotalAmout(NumberUtil.add(dto.getTaxAmout(), dto.getAmoutWithTax()));
        //默认未提交
        entity.setSubmitState(CodeConstant.COMM_CODE_0);
        //默认手工勾选
        entity.setSubmitMode(CodeConstant.COMM_CODE_0);
        baseMapper.insert(entity);
    }

    /**
     * 电子底账库更新
     *
     * @param dto
     * @param entity
     */
    private void updateData(InvoiceListDTO dto, ElectronicledgerEntity entity) {
        if (!(CodeConstant.COMM_CODE_2.equals(entity.getAuthState()) && CodeConstant.COMM_CODE_0.equals(dto.getAuthState()))) {
            entity.setAuthState(dto.getAuthState());
        }
        entity.setAuthDate(dto.getAuthDate());
        entity.setAuthPeriod(dto.getAuthPeriod());
        entity.setInvoiceState(dto.getInvoiceState());
        entity.setAuthMode(dto.getAuthMode());
        entity.setManagementState(dto.getManagementState());
        entity.setAbnormalType(dto.getAbnormalType());
        baseMapper.updateById(entity);
    }

    /**
     * 更新公司初始化标记
     *
     * @param taxNo
     */
    private void updateCompanyInitFlag(String taxNo) {
        baseMapper.updateCompanyInitFlag(taxNo);
    }

    /**
     * 申请统计汇总表（查询）
     *
     * @param query
     * @return
     */
    public Response<Map<String, Object>> querySummary(InvoiceSummaryDTO query) {
        query.setPeriod(query.getPeriod().replace("-", ""));
        List<InvoiceSummaryVO> invoiceSummaryVOList = baseMapper.selectSummary(query);
        HashMap<String, Object> map = new HashMap<>();
        InvoiceSummaryCountVO invoiceSummaryCountVO = new InvoiceSummaryCountVO();
        invoiceSummaryCountVO.setName("合计");
        for (InvoiceSummaryVO invoiceSummaryVO : invoiceSummaryVOList) {
            invoiceSummaryCountVO.setCountByfs(invoiceSummaryCountVO.getCountByfs() + invoiceSummaryVO.getFs());
            invoiceSummaryCountVO.setCountByje(invoiceSummaryCountVO.getCountByje().add(invoiceSummaryVO.getJe()));
            invoiceSummaryCountVO.setCountByse(invoiceSummaryCountVO.getCountByse().add(invoiceSummaryVO.getSe()));
        }
        map.put("hj", invoiceSummaryCountVO);
        map.put("info", invoiceSummaryVOList);
        return Response.success(map);
    }

    /**
     * 申请统计结果汇总表查询
     *
     * @param query
     * @return
     */
    public Response queryResultSummary(PageRequest<InvoiceSummaryDTO> query) {
        InvoiceSummaryDTO info = query.getInfo();
        info.setPeriod(info.getPeriod().replace("-", ""));
        List<InvoiceResultSummaryVO> invoiceSummaryVOS = baseMapper.queryResultSummary(query);
        IPage<InvoiceResultSummaryVO> iPage = new Page<>();
        iPage.setRecords(invoiceSummaryVOS);
        iPage.setCurrent(query.getPage().getCurrentPage());
        if (!invoiceSummaryVOS.isEmpty()) {
            iPage.setTotal(invoiceSummaryVOS.size());
        } else {
            iPage.setTotal(0);
        }
        iPage.setPages(query.getPage().getCurrentPage());
        iPage.setSize(query.getPage().getPageSize());
        return Response.success(iPage);
    }

    /**
     * @throws Exception
     */
    public void timedDataHandling() {
        //查询需要同步的税号
        List<String> nsrsbhList = managerClientService.getTaxNumbers("", CommonConstant.AUTH_TYPE_3).getData();
        log.info("定时任务电子底账同步接口税号：{}", JSON.toJSONString(nsrsbhList));
        if (nsrsbhList != null && nsrsbhList.size() > 0) {
            for (String taxNo : nsrsbhList) {
                asyncTreadPoolConfig.getAsyncExecutor().execute(() ->
                        callRemoteService(taxNo, CodeConstant.DEFAULT_SYNCTYPE, null)
                );
            }
        }
    }
}
